package org.acooke.uykfd.db

import java.lang.StringBuilder
import java.util.ArrayList
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.empire.db.DBColumn
import org.apache.empire.db.DBExpr
import org.apache.empire.db.DBDatabase
import org.apache.empire.db.DBTable
import org.apache.empire.db.DBTableColumn

class ScalaTable[F](name: String, database: DBDatabase, factory: F)
  extends DBTable(name, database) {

  val orm = factory

  def clone[F, T <: ScalaTable[F]] = {
    try {
      val clone = super.clone match {
        case ok: T => ok
        case err => throw new ClassCastException("Clone gave " + err.getClass.getName)
      }
      // clone all columns
      val colClass = columns.get(0).getClass
      val colBase = colClass.getSuperclass
      clone.columns = new ArrayList[DBColumn]
      var clazz = getClass
      while (clazz != classOf[DBTable]) {
        val fields = clazz.getDeclaredFields
        for (i <- 0 until columns.size) {
          val srcCol = columns.get(i)
          val newCol = srcCol match {
            case col: DBTableColumn => 
              new DBTableColumn(clone, col.getDataType, col.getName, col.getSize, col.isRequired, col.getDefaultValue)
            case x => throw new ClassCastException("ScalaTable does not support " + x.getClass.getName)
          }
          // Replace all references for oldCol to newCol
          for (j <- 0 until fields.length) {
            // Find a class of Type DBColumn or DBTableColumn
            val tipe = fields(j).getType
            if (tipe == colClass || tipe == colBase) {
              try {
                // Check if the field points to the old Value
                val getter = clazz.getDeclaredMethod(fields(j).getName)
                if (getter.invoke(clone) == srcCol) {
                  val setter = clazz.getDeclaredMethod(fields(j).getName + "_$eq", tipe)
                  setter.invoke(clone, newCol)
                }
              } catch {
                case e: Exception => 
                  // IllegalAccessException or IllegalArgumentException
                  throw new Exception("Cannot clone table-member: " + fields(j).getName + "-->" + e.getMessage)
              }
            }
          }
        }
        clazz = clazz.getSuperclass()
      }
      // set new alias
      clone
    } catch {
      case e: CloneNotSupportedException => null
    }
  }

}

